"use strict";

const path = require("path");
const fse = require("fs-extra");
const pathExists = require("path-exists").sync;
const pkgDir = require("pkg-dir").sync;
const npminstall = require("npminstall");
const { isObject } = require("@test-cli/utils");
const {
  getDefaultRegistry,
  getNpmLatestVersion
} = require("@test-cli/get-npm-info");
const formatPath = require("@test-cli/format-path");

class Package {
  constructor(options) {
    if (!options) {
      throw new Error("Package类的options参数不能为空！");
    }

    if (!isObject(options)) {
      throw new Error("Package类的options必须为对象！");
    }

    // package路径
    this.targetPath = options.targetPath;
    // 缓存 package 路径
    this.storeDir = options.storeDir;
    // package name
    this.packageName = options.packageName;
    // package 版本号
    this.packageVersion = options.packageVersion;

    this.cacheFilePathPrefix = this.packageName.replace("/", "_");
  }

  async prepare() {
    // 生成缓存目录
    if (this.storeDir && !pathExists(this.storeDir)) {
      fse.mkdirpSync(this.storeDir);
    }

    if (this.packageVersion === "latest") {
      this.packageVersion = await getNpmLatestVersion(this.packageName);
    }
  }

  get cacheFilePath() {
    return path.resolve(
      this.storeDir,
      `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`
    );
  }

  // 判断package是否存在
  async exits() {
    if (this.storeDir) {
      // 缓存模式
      await this.prepare();
      return pathExists(this.cacheFilePath);
    } else {
      return pathExists(this.targetPath);
    }
  }

  // 安装
  async install() {
    await this.prepare();
    return npminstall({
      root: this.targetPath,
      storeDir: this.storeDir,
      registry: getDefaultRegistry(),
      pkgs: [{ name: this.packageName, version: this.packageVersion }]
    });
  }

  // 更新
  async update() {
    await this.prepare();
    // 1. 获取最新npm模块版本号
    // 2. 查询最新版本号对应路径是否存在
    // 3. 如果不存在
    const latestPackageVersion = await getNpmLatestVersion(this.packageName);
    const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion);

    if (!pathExists(latestFilePath)) {
      await npminstall({
        root: this.targetPath,
        storeDir: this.storeDir,
        registry: getDefaultRegistry(),
        pkgs: [{ name: this.packageName, version: latestPackageVersion }]
      });
    }

    this.packageVersion = latestPackageVersion;
  }

  getSpecificCacheFilePath(packageVersion) {
    return path.resolve(
      this.storeDir,
      `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`
    );
  }

  // 获取入口文件路径
  getRootFilePath() {
    // 1.获取package.json所在目录 -> pkg-dir(npm)
    // 2.读取package.json
    // 3.寻找main/lib
    // 4.路径兼容

    function _getRootFile(targetPath) {
      const dir = pkgDir(targetPath);
      if (dir) {
        const pkgFile = require(path.resolve(dir, "package.json"));
        if (pkgFile && pkgFile.main) {
          // 路径兼容
          return formatPath(path.resolve(dir, pkgFile.main));
        }
      }
      return null;
    }

    if (this.storeDir) {
      return _getRootFile(this.cacheFilePath);
    } else {
      return _getRootFile(this.targetPath);
    }
  }
}

module.exports = Package;
